WebサイトにCloudFront Functionを設定したら接続が503エラーとなったのでトラブルシュートしてみた
こんにちは、CX事業本部の若槻です。
今回は、WebサイトにCloudFront Functionを設定したら接続が503エラーとなったのでトラブルシュートをした際の話です。
CloudFront Functionを設定したら503エラーが発生
前回のエントリでCloudFront + S3な構成の静的ウェブサイトにCloudFront Functionを設定しました。
その際にこのエントリ中では触れていませんでしたが、実装の検証をする中で設定前にはアクセスできていたWebサイトにCloudFront Functionを設定したら接続が503エラーとなる時がありました。
その時に使用したCloudFront Functionのコードは下記です。Lambda@Edgeでは同じコードで問題なく動いていました。
exports.handler = (event) => { const request = event.request; const headers = request.headers; // echo -n user:pass | base64 const authString = "Basic dXNlcjpwYXNz"; if ( typeof headers.authorization === "undefined" || headers.authorization.value !== authString ) { return { statusCode: 401, statusDescription: "Unauthorized", headers: { "www-authenticate": { value: "Basic" } } }; } return request; }
上記をCDKデプロイして、Webサイトに接続すると下記のように503エラーが発生しました。
503 ERROR
The request could not be satisfied.The CloudFront function associated with the CloudFront distribution is invalid or could not run. We can't connect to the server for this app or website at this time. There might be too much traffic or a configuration error. Try again later, or contact the app or website owner.
If you provide content to customers through CloudFront, you can find steps to troubleshoot and help prevent this error by reviewing the CloudFront documentation.Generated by cloudfront (CloudFront)
Request ID: SWBACG0l6Yl9xl5VDpRafMfdmjySTCaRLAxuCAA877pZvQ4Z1Gu8DY==
調査、原因
5XXエラーということはサーバー側で何かしらのエラーが発生しており、直前に設定したCloudFront Functionがほぼほぼ原因でしょう。しかしLambda@Edgeでは動いていたコードがなぜ?という気持ちです。
ということで調査のためにAWSコンソールから情報を確認してみます。まずCloudFront > Telemetry > Monitoring で[Functions]タブを開いてみると先ほど作成したFunctionがあったので選択して[View function metrics]をクリックしてみます。
すると通常のLambdaのページでも見られるようなメトリクスのダッシュボードが見られました。ページを下の方へスクロールすると、
[Execution Erros]で先ほど発生したと思わしきエラーも確認できました。
ページを上へ戻り、次は[View function logs]をクリックしてみます。
するとCloudWatch Logsのページが開くのですが、log groupが存在しない旨のエラーとなりました。
実行時に自動でlog groupが作成される通常のLambdaと異なり、CloudFront Functionは明示的にlog groupを作成する必要があるのでしょうか。(これについてはまたの機会にやってみます)
次にCloudFront > Functionsを開くと先ほど作成したFunctionがあるのでこちらも開いてみます。
Functionの設定をするためのコンソールが開けました。CDKで実装時は使用しませんでしたが、手動設定する場合はこちらから出来そうです。
[Test]タブからはコードのテストが出来そうです。[Test]をクリックしてみます。
すると実行がエラーとなりエラーメッセージが出力されました。
どうやらCloudFront Functionではconst
が使えないようです。
Error Message: The CloudFront function associated with the CloudFront distribution is invalid or could not run. SyntaxError: Token "const" not supported in this version in 2
[Build]タブに戻りコードを編集してconst
をvar
に変更してみます。[Save]で変更を保存します。
exports.handler = (event) => { var request = event.request; var headers = request.headers; // echo -n user:pass | base64 var authString = "Basic dXNlcjpwYXNz"; if ( typeof headers.authorization === "undefined" || headers.authorization.value !== authString ) { return { statusCode: 401, statusDescription: "Unauthorized", headers: { "www-authenticate": { value: "Basic" } } }; } return request; }
[Test]タブに戻り再度テストを実行するとまた実行エラーとなりました。
CloudFront Functionではexports
が使えないようです。
Error Message: The CloudFront function associated with the CloudFront distribution is invalid or could not run. ReferenceError: "exports" is not defined in 1
また[Build]タブに戻りコードを下記のようにexports
を使用しない記述に変更してみます。[Save]で変更を保存します。
function handler(event) { var request = event.request; var headers = request.headers; //(中略)
もう一度テストを実行してみると今度は成功しました。ステータスが401
となっておりちゃんとFunctionによるBasic認証の要求が働いているようです。
テストが成功したコードを使用してCDKデプロイし、Webサイトにアクセスしてみると次はちゃんとエラーなく動作しました。
おわりに
前回のエントリでのBuffer
と同様に、今回のconst
やexports
など、Lambda@Edgeでは当たり前のように使えていたモジュールがCloidFront Functionでは使えないことにより遭遇したトラブルでした。というのもCloudFront Functionのランタイムは「ECMAScript 5.1 compliant」だからです。
最新のフルセットのNode.jsランタイムを使わないことにより、読み込むモジュールを軽量化してFunctionの実行の高速化を図っているのでしょうね。
参考
以上